import React, { ReactElement, useState, useEffect } from 'react'
import classnames from 'classnames'
import { PlusOutlined } from '@ant-design/icons'
import style from './Form.module.less'
import Agree from './Agree'
import { awaitWrap, getObjectURL } from '@js/tool'
import { requestOneFile, UploadRes } from '@js/request'
import { getCardInfoRequest, submitRequest, getCaseListRequest } from '../ajax'
import { message } from 'antd'
import { connect, useDispatch } from 'react-redux'
import { BASIC_STATE } from '@redux/reducers/basic'
import { setLogout, setUserInfo, USERINFO } from '@redux/actions/basic'
import { History } from 'history'
import _ from 'lodash'
import { useHistory } from 'react-router-dom'

interface Props {
  userInfo: USERINFO
  setUserInfo: (u: USERINFO) => void
  history: History
}

interface Img {
  file: File
  url: string
  id: string
  info: {
    name: string
    num: string
  }
}

// 改变文件
async function changeFile (e: React.ChangeEvent<HTMLInputElement>, type: string, setFn: (v: Img) => void): Promise<void> {
  const files = e.target.files
  if (!(files instanceof FileList)) {
    return undefined
  }
  if (files.length === 0 || !(files[0] instanceof File)) {
    return undefined
  }
  const file = files[0]
  if (!['image/jpeg', 'image/png', 'image/jpg'].includes(file.type)) {
    return await message.warning('请上传格式为png、jpg或jpeg的图片')
  }
  const f: Img = {
    file,
    url: getObjectURL(file),
    id: '',
    info: {
      name: '',
      num: ''
    }
  }
  await initCardInfo(f, type, setFn)
}

// 上传图片
async function uploadFile (file: File): Promise<UploadRes> {
  const [e, d] = await awaitWrap(requestOneFile(file))
  if (e !== null) {
    throw new Error(e.message)
  }
  if (d === null) {
    throw new Error('上传文件，返回数据为空')
  }
  return d
}

// 获取身份证信息
async function initCardInfo (img: Img, type: string, setFn: (v: Img) => void): Promise<void> {
  const hide = message.loading('提交中', 120)
  const [fe, fd] = await awaitWrap(uploadFile(img.file))
  if (fe !== null) {
    hide()
    return undefined
  }
  if (fd === null) {
    hide()
    return undefined
  }
  const [e, d] = await awaitWrap(getCardInfoRequest(fd.url, type))
  hide()
  if (e !== null || d === null) {
    console.error(e)
    await message.error(`获取身份证${type}信息失败`)
    return undefined
  }
  setFn({ ...img, id: fd.id, info: d })
}

// 提交
async function submitHandle (submitable: boolean, front: Img | null, back: Img | null, history: History, userInfo: USERINFO, setUserInfo: (u: USERINFO) => void): Promise<void> {
  if (!submitable || front === null || back === null) {
    return undefined
  }
  const hide = message.loading('提交中', 120)
  const [e] = await awaitWrap(submitRequest(front.info.name, front.info.num, front.id, back.id))
  hide()
  if (e !== null) {
    message.warning(e.message).then(null, null)
    return undefined
  }
  const u = _.cloneDeep(userInfo)
  if (u.is_auth === 0) {
    u.is_auth = 1
    u.realname = front.info.name
    setUserInfo(u)
  }
  await decideJump(history)
}

// 根据案件列表数量决定验证后跳转的页面
async function decideJump (history: History): Promise<void> {
  const hide = message.loading('加载中', 120)
  const [e, d] = await awaitWrap(getCaseListRequest())
  hide()
  if (e !== null || d === null) {
    history.push('/')
  } else if (d !== null || d !== 0) {
    history.push('/admin/case-list')
  } else {
    history.push('/admin/new-case')
  }
}

function Main ({ userInfo, setUserInfo, history }: Props): ReactElement {
  const [submitable, setSubmitable] = useState(false)
  const [agree, setAgree] = useState(true)
  const [front, setFront] = useState<Img|null>(null)
  const [back, setBack] = useState<Img|null>(null)
  const submitName = classnames(style.submit, { [style.active]: submitable })
  const dispatch = useDispatch()
  const h = useHistory()
  useEffect(() => {
    if (userInfo !== null && userInfo.is_auth !== 0) {
      return message.warning('本账号已完成实名认证', 2, () => {
        decideJump(history).catch(e => console.error(e))
      })
    }
  }, [])
  useEffect(() => {
    setSubmitable(agree && front !== null && front.info !== null && back !== null && back.info !== null)
  }, [agree, front, back])
  return (
    <div className={style.container}>
      <div className={style['title-line']}>实名认证</div>
      <div className={style['sub-title-line']}>根据网络仲裁规则规定，需要身份与账号绑定</div>
      <div className={style['identity-line']}>
        <div className={style['identity-block']}>
          <label className={style.front}>
            <input type='file' onChange={async e => await changeFile(e, '正面', setFront)} />
            <span><PlusOutlined /></span>
            {front !== null && <img src={front.url} alt='' />}
          </label>
          <span>上传证件正面照</span>
        </div>
        <div className={style['identity-block']}>
          <label className={style.back}>
            <input type='file' onChange={async e => await changeFile(e, '背面', setBack)} />
            <span><PlusOutlined /></span>
            {back !== null && <img src={back.url} alt='' />}
          </label>
          <span>上传证件国徽照</span>
        </div>
      </div>
      <Agree value={agree} onChange={v => setAgree(v)} />
      <button className={submitName} onClick={async () => await submitHandle(submitable, front, back, history, userInfo, setUserInfo)}>提交</button>
      <button className={style.cancel} onClick={() => { dispatch(setLogout()); h.replace('/login') }}>取消</button>
    </div>
  )
}

export default connect((state: { basic: BASIC_STATE }) => {
  return {
    userInfo: state.basic.userInfo
  }
}, dispatch => {
  return {
    setUserInfo: (u: USERINFO) => dispatch(setUserInfo(u))
  }
})(Main)
